import LogFactory from "log/LogFactory";

/**
 * 数组比较结果
 */
export type CompareArrayResult = {
    /**
     * 需要更新的用户id,提交请求时需要使用
     */
    id?: number,
    /**
     * 是否存在差异,如果反回true,则说明有差异
     */
    isUpdate?: boolean ,
    /**
     * 新增的元素
     */
    addNodes?: string[] ,
    /**
     * 删除的元素
     */
    deleteNodes?: string[] ,
}

const log = LogFactory.getLog("compare") ;
/**
 * 比较两个对象的差异,并合并属性
 * 将fresh中存在的属性合并到origin中,如果origin中存在,则覆盖
 * 如果fresh中的属性值为null,则不合并
 *
 * @param origin 需要合并属性的原始对象
 * @param fresh  需要比较合并属性的对象
 * @returns {origin} 返回合并后的对象(origin) 如果fresh中的属性值为null则直接反回origin
 */
export const compareObjectMergeProps = <T extends object> (origin: T ,fresh: T): T => {
    let keys = Object.keys(fresh) ;
    keys.forEach( key => {
        origin[key as keyof T] = fresh[key as keyof T] ;
    }) ;
    return origin ;
} ;

/**
 * 比较两个数组的差异,以origin为基准
 * @param origin 源数组
 * @param fresh 修改后的数组,需要比较的数组
 * @returns {CompareArrayResult} isUpdate: true 有差异, false 无差异
 * @returns {CompareArrayResult} addNodes: 新增的元素
 * @returns {CompareArrayResult} deleteNodes: 删除的元素
 */
export const compareArray = (origin: string[] ,fresh:string[]): CompareArrayResult => {
    origin === void 0 && (origin = []) ;
    fresh === void 0 && (fresh = []) ;
    let res: CompareArrayResult = {
        isUpdate: false ,
        addNodes: [] ,
        deleteNodes: [] ,
    } ;

    // 如果两个数组都为空,则表示无差异
    if (origin.length === 0 && fresh.length ===0){
        return res ;
    }
    // 如果新的数组为空,源数组不为空,则表示删除全部数据
    if (fresh.length === 0 && origin.length !==0){
        res.isUpdate = true ;
        res.deleteNodes = origin ;
        return res ;
    }
    // 如果源数组为空,新数组不为空,则表示新增全部数据
    if (origin.length === 0 && fresh.length !==0){
        res.isUpdate = true ;
        res.addNodes = fresh ;
        return res ;
    }
    // 如果两个数组都不为空,则需要比较差异
    res.addNodes = checkAddNodes(origin ,fresh) ;
    res.deleteNodes = checkDelNodes(origin ,fresh);
    res.isUpdate = res.addNodes.length !== 0 || res.deleteNodes.length !== 0 ;
    return res;
};
const checkAddNodes = (origin: string[] ,fresh: string[]): string[] => {
    return fresh.filter(e => !origin.includes(e)) ;
} ;
const checkDelNodes = (origin: string[] ,fresh: string[]): string[] => {
    return origin.filter(e => !fresh.includes(e)) ;
} ;
/**
 * 比较两个对象的差异,以fresh为基准,只比较一层.比较fresh中的属性
 * @param origin 源对象
 * @param fresh 修改后的对象,需要比较的对象
 * @returns {any} 返回差异对象,如果没有差异,则返回null
 */
export const compareObject = (origin: any ,fresh: any): any | null => {
    // console.log(origin ,fresh)
    let keys = Object.keys(fresh) ;
    let flag: boolean = false ;

    keys.forEach(key => {
        // console.log(origin[key],fresh[key],"比较",origin[key] === fresh[key])
        if (origin[key] === fresh[key]){
            // console.log('相等',fresh[key])
            delete fresh[key] ;
        }else {
            flag = true ;
            // console.log('不相等',fresh[key])
        }
        // if (origin[key] === fresh[key]){
        //     console.log('相等',)
        // }
    }) ;

    if (flag){
        return fresh ;
    }else {
        return null ;
    }
} ;

/**
 * 比较两个对象的差异,以fresh为基准,遍历fresh中的属性,此方法只比较一层,并且对象中的属性值为基本类型
 * <li>如果两个对象没有差异: fresh中的全部属性值和origin中的一致,则反回空值</li>
 * <li>如果两个对象存在差异,则反回差异对象,对象中值包含origin和fresh中都存在的属性,并且属性的值不一致</li>
 * @param origin 需要比较的原始对象
 * @param fresh 需要比较对象的新属性对象[此对象为基准比较,只比较fresh中的属性]
 * @returns {Partial<T> | null} 返回差异对象,如果没有差异,则返回null
 */
export const compareObjectToDifference = <T extends object> (origin: T,fresh: T): Partial<T> | null => {
    let keys = Object.keys(fresh) ;
    let res: Partial<T> = {} ;
    let flag: boolean = false ;
    keys.forEach(key => {
        if (origin[key as keyof T] !== fresh[key as keyof T]){
            res[key as keyof T] = fresh[key as keyof T] ;
            flag = true ;
        }
    }) ;
    return flag ? res : null ;
} ;

